package com.amap.search.task;

import com.amap.search.entity.db2022.AddressCode;
import com.amap.search.entity.db2022.AmapPlanExecution;
import com.amap.search.entity.db2022.PoiCode;
import com.amap.search.mapper.db2022.AddressCodeMapper;
import com.amap.search.mapper.db2022.AmapPlanExecutionMapper;
import com.amap.search.mapper.db2022.PoiCodeMapper;
import com.amap.search.service.AmapHttpService;
import com.amap.search.service.ElasticSearchOperatorService;
import com.amap.search.util.RestHttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SearchPoiTask {
    @Resource
    private AmapHttpService amapHttpService;

    @Resource
    private AddressCodeMapper addressCodeMapper;

    @Resource
    private PoiCodeMapper poiCodeMapper;

    @Resource
    private AmapPlanExecutionMapper planExecutionMapper;

    @Resource
    private ElasticSearchOperatorService elasticSearchOperatorService;

    // 感兴趣的景点列表
//    private List<String> poiList = Arrays.asList("动物园", "植物园", "世界遗产", "国家级景点");
    private List<String> poiList = Arrays.asList("肯德基", "麦当劳", "巴西菜", "泰国/越南菜品餐厅");

    // poi从poiList[poiIndex]搜起
    private int poiIndex = 0;

    // 记录上次搜寻的城市Code,小于等于该Code的不再重复搜索
    private String nowCityCode = "0";

    private List<String> specialCityCode = Arrays.asList("110100", "120100", "500100", "310100");

    /**
     * 每天跑一次，搜索各城市的景点，直至5000次用完
     * 每次请求间隔2s 避免被墙
     */
    @Scheduled(cron = "0 41 18 * * ?")
    public void runJob() {
        log.info("**** 定时任务开始 ****");
        // 从上次终止的地方开始搜索
        List<PoiCode> poiCodeList = poiCodeMapper.queryPoiFromNameList(poiList);
        setLatestPlace(poiCodeList);
        // 获取映射
        List<String> poiCodes = poiCodeList.stream().map(PoiCode::getTypeCode).collect(Collectors.toList());
        while (poiIndex < poiCodeList.size()) {
            List<AddressCode> cityList = addressCodeMapper.queryAllCity(nowCityCode);
            cityList = cityList.stream().sorted((Comparator.comparing(AddressCode::getCityCode))).collect(Collectors.toList());
            for (AddressCode city : cityList) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                    String cityCode = city.getCityCode();
                    if(specialCityCode.contains(city.getCityCode())){
                        cityCode = city.getProvinceCode();
                    }
                    amapHttpService.searchPoiFromCity(cityCode, poiCodes.get(poiIndex));
                    nowCityCode = city.getCityCode();
                } catch (Exception e) {
                    log.info("请求异常 ： ", e);
                    saveRecordWhenException(poiCodes.get(poiIndex), city.getCityCode());
                    return;
                }
            }
            // 所有城市搜索完成, 搜索下一景点
            poiIndex++;
            nowCityCode = "0";
        }
    }

    private void saveRecordWhenException(String typeCode, String cityCode){
        AmapPlanExecution amapPlanExecution = new AmapPlanExecution();
        amapPlanExecution.setExecuteDate(new Date());
        amapPlanExecution.setRecordCount(RestHttpUtil.getRequestCount);
        amapPlanExecution.setTypeCode(typeCode);
        amapPlanExecution.setCityCode(cityCode);
        planExecutionMapper.insert(amapPlanExecution);
        elasticSearchOperatorService.pushElement();
    }

    private void setLatestPlace(List<PoiCode> poiCodeList){
        AmapPlanExecution amapPlanExecution = planExecutionMapper.queryLatestRecord();
        if(amapPlanExecution != null){
            nowCityCode = amapPlanExecution.getCityCode();
            for(int i=0; i<poiCodeList.size(); i++){
                if(poiCodeList.get(i).getTypeCode().equals(amapPlanExecution.getTypeCode())){
                    poiIndex = i;
                    break;
                }
            }
        }
    }
}
